﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.DataAbstraction;
using EPiServer.Data.Dynamic;
using EPiServer.Data;
using EPiServer.Core;

namespace EPiServer.DdsPageProvider
{
    public class PropertyMapper
    {
        string prefix;
        DynamicDataStoreFactory ddsFactory;

        public PropertyMapper(string prefix, DynamicDataStoreFactory ddsFactory)
        {
            this.prefix = prefix;
            this.ddsFactory = ddsFactory;
        }

        public IDictionary<long, string> GetOrCreateTypeStores(Func<PageTypeCollection> getPageTypes)
        {
            Dictionary<long, string> typeToStoreMap = new Dictionary<long, string>();
            foreach (PageType type in getPageTypes())
            {
                var store = GetOrCreateStore(type);

                typeToStoreMap[type.ID] = store.Name;
            }
            return typeToStoreMap;
        }

        public DynamicDataStore GetOrCreateStore(PageType type)
        {
			DynamicDataStore store = GetStore(type);

            if (store == null)
            {
                var map = ToTypeMap(type);
                map["NodeId"] = typeof(Identity);
				var indexedColumns = new StoreDefinitionParameters();
				indexedColumns.IndexNames.Add("NodeId");
				
				store = ddsFactory.CreateStore(GetStoreName(type), map, indexedColumns);
            }

            return store;
        }

		public DynamicDataStore GetStore(PageType type)
		{
			return ddsFactory.GetStore(GetStoreName(type));
		}

		private string GetStoreName(PageType type)
		{
			return prefix + type.GUID.ToString().Replace('-', '_');
		}

        private IDictionary<string, Type> ToTypeMap(PageType type)
        {
            Dictionary<string, Type> typeBag = new Dictionary<string, Type>();
            foreach (var propertyDefinition in type.Definitions)
            {
				typeBag[propertyDefinition.Name.ToStoreString()] = GetPropertyType(propertyDefinition.Type.DataType);
            }
            return typeBag;
		}

		static Type GetPropertyType(PropertyDataType type)
		{
			switch (type)
			{
				case PropertyDataType.Boolean:
					return typeof(bool);

				case PropertyDataType.Number:
					return typeof(long);

				case PropertyDataType.FloatNumber:
					return typeof(double);

				case PropertyDataType.PageType:
					return typeof(int);

				case PropertyDataType.PageReference:
					return typeof(string);

				case PropertyDataType.Date:
					return typeof(DateTime);

				case PropertyDataType.String:
					return typeof(string);

				case PropertyDataType.LongString:
					return typeof(string);

				case PropertyDataType.Category:
					return typeof(int);

				default:
					throw new NotSupportedException("Not supported: " + type);
			}
		}
    }

}
